﻿using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace YunHao
{
    /// <summary>
    /// json相关的操作
    /// </summary>
    public class JsonControl
    {
        /// <summary>
        /// 读取普通json文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public static T ReadJson<T>(string path)
        {
            string json = File.ReadAllText(path);
            return JsonUtility.FromJson<T>(json);
        }

        /// <summary>
        /// 保存普通json文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <param name="data"></param>
        public static void WriteJson<T>(string path, T data)
        {
            string json = JsonUtility.ToJson(data);
            File.WriteAllText(path, json);
        }

        /// <summary>
        /// 读取加密json文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public static T ReadCryptoJson<T>(string path)
        {
            string cryptoJson = File.ReadAllText(path);
            string json = CryptoString.Decrypt(cryptoJson);
            return JsonUtility.FromJson<T>(json);
        }

        /// <summary>
        /// 写入加密json文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <param name="data"></param>
        public static void WriteCryptoJson<T>(string path, T data)
        {
            string json = JsonUtility.ToJson(data);
            string cryptoJson = CryptoString.Encrypt(json);
            File.WriteAllText(path, cryptoJson);
        }

        /// <summary>
        /// serialize list to json
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static string ListToJson<T>(List<T> list)
        {
            return JsonUtility.ToJson(new Serialization<T>(list));
        }

        /// <summary>
        /// deserialize list from json
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static List<T> ListFromJson<T>(string json)
        {
            var serialization = JsonUtility.FromJson<Serialization<T>>(json);
            return serialization.ToList();
        }

        /// <summary>
        /// serialize dictionary to json
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static string DictionaryToJson<T, K>(Dictionary<T, K> dictionary)
        {
            return JsonUtility.ToJson(new Serialization<T, K>(dictionary));
        }

        /// <summary>
        /// deserialize dictionary from json
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static Dictionary<T, K> DictionaryFromJson<T, K>(string json)
        {
            var serialization = JsonUtility.FromJson<Serialization<T, K>>(json);
            return serialization.ToDictionary();
        }

    }

    /// <summary>
    /// List<T> used when serialize list to json
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Serializable]
    public class Serialization<T>
    {
        [SerializeField]
        private List<T> target;
        public List<T> ToList() { return target; }

        public Serialization(List<T> target)
        {
            this.target = target;
        }
    }

    /// <summary>
    /// Dictionary<TKey, TValue> used when serialize dictionary to json
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    [Serializable]
    public class Serialization<TKey, TValue> : ISerializationCallbackReceiver
    {
        [SerializeField]
        List<TKey> keys;
        [SerializeField]
        List<TValue> values;

        private Dictionary<TKey, TValue> target;

        public Dictionary<TKey, TValue> ToDictionary() { return target; }

        public Serialization(Dictionary<TKey, TValue> target)
        {
            this.target = target;
        }

        public void OnBeforeSerialize()
        {
            keys = new List<TKey>(target.Keys);
            values = new List<TValue>(target.Values);
        }

        public void OnAfterDeserialize()
        {
            var count = Math.Min(keys.Count, values.Count);
            target = new Dictionary<TKey, TValue>(count);
            for (var i = 0; i < count; ++i)
            {
                target.Add(keys[i], values[i]);
            }
        }
    }
}